package com.zzl.java8.lambda7;

import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.function.*;
import java.util.stream.Collectors;

/**
 * description: 函数式编程
 * @author 朱正磊
 * @date 2019-08-09 15:14:22
 */
public class MyLambda {

    /**
     * description: 测试自定义接口
     * @author 朱正磊
     * @date 2019-08-12 11:22:11
     */
    @Test
    void testMyInterface() {

        //1、原始写法：面向接口编程
        MyInterface myInterface1 = new MyInterface() {
            @Override
            public void run() {
                System.out.println("======run======");
            }

            @Override
            public String sup() {
                return "======sup======";
            }

            @Override
            public void sum(String name) {
                System.out.println("======sum【"+ name +"】======");
            }

            @Override
            public String fun(String param) {
                return "======fun【"+ param +"】======";
            }

            @Override
            public String sta(String name, Integer age) {
                return "======sta【"+ name + "..." + age +"】======";
            }
        };

        myInterface1.run();
        String sup = myInterface1.sup();
        System.out.println(sup);
        myInterface1.sum("lisi");
        String zhangsan = myInterface1.fun("zhangsan");
        System.out.println(zhangsan);
        String zzl = myInterface1.sta("zzl", 28);
        System.out.println(zzl);
    }

    /**
     * description: 测试我的自定义接口（只有一个抽象方法），与Runnable异曲同工
     * @author 朱正磊
     * @date 2019-08-12 13:53:28
     */
    @Test
    void testMyRun() {
        MyRun myRun1 = new MyRun() {
            @Override
            public void run() {
                System.out.println("面向接口编程：我的自定义接口（只有一个抽象方法）");
            }
        };
        myRun1.run();

        MyRun myRun2 = () -> System.out.println("lambda：我的自定义接口（只有一个抽象方法）");
        myRun2.run();
    }

    /**
     * description: 测试匿名函数
     * @author 朱正磊
     * @date 2019-08-09 16:43:33
     */
    @Test
    void testThread() {

        //1、原始写法：面向接口编程
        Runnable runnable1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("I am very happy");
            }
        };
        Thread thread1 = new Thread(runnable1);

        //2、使用lambda表达式进行编程
        Runnable runnable2 = () -> System.out.println("I am very happy");
        Thread thread2 = new Thread(runnable2);

        //3、简化写法
        Thread thread3 = new Thread(() -> System.out.println("I am very happy"));

    }

    /**
     * description: 测试Supplier（供给型接口）
     * @author 朱正磊
     * @date 2019-08-09 15:15:08
     */
    @Test
    void testSupplier() {

        //其中泛型表示返回值类型
        Supplier<Integer> age = () -> 2;

        Supplier<String> title = () -> "hello world";
        //hello world
        System.out.println(title.get());

        Supplier<Index> supplier = Index::new;
        Index index = supplier.get();
        index.setTitle("于何");
        System.out.println(index.getTitle());

        Supplier<LinkedList> sl = LinkedList::new;
        LinkedList linkedList = sl.get();
        System.out.println(linkedList.size());

    }

    /**
     * description: 测试Consumer（消费型接口）
     * @author 朱正磊
     * @date 2019-08-09 15:21:49
     */
    @Test
    void testConsumer() {

        //其中泛型表示入参类型
        Consumer<Integer> consumer1 = e -> System.out.println(e++);

        Consumer<Integer> consumer2 = e -> System.out.println(e * 2);

        //11
        //20
        consumer1.andThen(consumer2).accept(10);

    }

    /**
     * description: 测试Function（函数型接口）
     * @author 朱正磊
     * @date 2019-08-09 15:18:31
     */
    @Test
    void testFunction() {
        //其中泛型第一个类型表示入参类型，第二个类型表示返回值类型
        Function<Integer, String> function1 = Object::toString;
        //10
        System.out.println(function1.apply(10));

        Function<String, String> function2 = e -> e + " hehe";
        //大熊 hehe
        System.out.println(function2.apply("大熊"));

        String apply = function1.andThen(function2).apply(1);
        //1 hehe
        System.out.println(apply);
    }

    /**
     * description: 测试Predicate（断言型接口）
     * @author 朱正磊
     * @date 2019-08-09 16:00:58
     */
    @Test
    void testPredicate() {
        //其中泛型表示入参类型
        Predicate<Integer> p = e -> e == 1;
        //true
        System.out.println(p.test(1));
    }

    /**
     * 提示：两个T作为输入，返回一个T作为输出，即传入的两个参数的类型和返回类型相同
     * description: 测试BinaryOperator（二元操作符）
     * @author 朱正磊
     * @date 2019-08-09 17:38:00
     */
    @Test
    void testBinaryOperator() {
        //其中泛型表示入参类型以及返回值类型，两个入参类型和返回值类型都是一样的
        BinaryOperator<Integer> add = (a, b) -> a + b;
        Integer result = add.apply(3, 4);
        //7
        System.out.println(result);

        BinaryOperator<String> concat = (x, y) -> x + y;
        String content = concat.apply("abc", "123");
        //abc123
        System.out.println(content);

        //比较大小（数字或字符串）
        //获取更小的值（自然排序）
        BinaryOperator<Integer> minI = BinaryOperator.minBy(Comparator.naturalOrder());
        Integer minIR = minI.apply(12, 99);
        System.out.println(minIR);

        //获取更大的值（自然排序）
        BinaryOperator<String> maxS = BinaryOperator.maxBy(Comparator.naturalOrder());
        String maxSR = maxS.apply("gtr", "sdf");
        System.out.println(maxSR);
    }

    /**
     * description: 综合函数式编程
     * @author 朱正磊
     * @date 2019-08-09 15:33:24
     */
    @Test
    void testAll() {

        List<Index> list = new ArrayList<>();
        Index index1 = new Index();
        index1.setTitle("zhangsan");
        Index index2 = new Index();
        index2.setTitle("lisi");
        Index index3 = new Index();
        index3.setTitle("yuhe");
        Index index4 = new Index();
        index4.setTitle("wangwu");
        list.add(index1);
        list.add(index2);
        list.add(index3);
        list.add(index4);

        list.stream().map(Index::getTitle).forEach(e -> {e = e + "1";
            System.out.println(e);});

        List<Index> resultList = list.stream()
                .filter(e -> !e.getTitle().equals("zhangsan"))
                .collect(Collectors.toCollection(LinkedList::new));

        List<Index> resultList2 = new LinkedList<>();
        for (Index index : list) {
            String title = index.getTitle();
            if (!"zhangsan".equals(title)) {
                resultList2.add(index);
            }
        }

        System.out.println(resultList.getClass());
        System.out.println(resultList.size());

    }

    /**
     * description: 测试BiFunction
     * @author 朱正磊
     * @date 2019-08-12 14:17:13
     */
    @Test
    void testBiFunction() {
        //其中泛型第一个类型表示第一个入参类型，第二个类型表示第二个入参类型，第三个类型表示返回值类型
        BiFunction<Integer, Long, String> biFunction = (x, y) -> x.toString() + " and " + y.toString();

        String result = biFunction.apply(12, 13L);

        //12 and 13
        System.out.println(result);
    }

}
